package com.uduemc.biso.node.web.service.impl;

import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;

import org.apache.velocity.Template;
import org.apache.velocity.app.VelocityEngine;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.util.HtmlUtils;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.googlecode.htmlcompressor.compressor.HtmlCompressor;
import com.uduemc.biso.core.common.extities.ctemplatelistdata.CTemplateItemData;
import com.uduemc.biso.core.extities.center.Host;
import com.uduemc.biso.core.utils.CryptoJava;
import com.uduemc.biso.core.utils.UserAgentUtil;
import com.uduemc.biso.node.core.common.entities.SRHtml;
import com.uduemc.biso.node.core.common.entities.SitePage;
import com.uduemc.biso.node.core.common.entities.ThemeObject;
import com.uduemc.biso.node.core.common.entities.srhtml.SRHead;
import com.uduemc.biso.node.core.common.entities.themeobject.ThemeObjectHtmlTag;
import com.uduemc.biso.node.core.common.entities.themeobject.ThemeObjectHtmlTagAttrs;
import com.uduemc.biso.node.core.common.entities.themeobject.ThemeObjectSource;
import com.uduemc.biso.node.core.common.utils.ThemeUtil;
import com.uduemc.biso.node.core.entities.HConfig;
import com.uduemc.biso.node.core.entities.HDomain;
import com.uduemc.biso.node.core.entities.SConfig;
import com.uduemc.biso.node.core.entities.SSeoItem;
import com.uduemc.biso.node.core.entities.SSystem;
import com.uduemc.biso.node.core.entities.custom.SSeoSiteSnsConfig;
import com.uduemc.biso.node.core.property.GlobalProperties;
import com.uduemc.biso.node.core.utils.SitePathUtil;
import com.uduemc.biso.node.web.component.RequestHolder;
import com.uduemc.biso.node.web.component.SiteHolder;
import com.uduemc.biso.node.web.component.SiteUrlComponent;
import com.uduemc.biso.node.web.entities.AccessHost;
import com.uduemc.biso.node.web.entities.AccessPage;
import com.uduemc.biso.node.web.entities.AccessSite;
import com.uduemc.biso.node.web.exception.NotFound404Exception;
import com.uduemc.biso.node.web.service.SRHeadService;
import com.uduemc.biso.node.web.service.SeoCodeService;
import com.uduemc.biso.node.web.service.ThemeService;
import com.uduemc.biso.node.web.service.byfeign.DeployService;
import com.uduemc.biso.node.web.service.byfeign.SeoService;
import com.uduemc.biso.node.web.service.byfeign.SiteConfigService;
import com.uduemc.biso.node.web.service.byfeign.TemplateService;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;

@Service("sRHeadServiceImpl")
public class SRHeadServiceImpl implements SRHeadService {

	private static final Logger logger = LoggerFactory.getLogger(SRHeadServiceImpl.class);

	public static String[] AUTHOR = { "all", "site" };

	@Autowired
	private ThemeService themeServiceImpl;

	@Autowired
	private RequestHolder requestHolder;

	@Autowired
	private SeoCodeService seoCodeServiceImpl;

	@Autowired
	private SeoService seoServiceImpl;

	@Autowired
	private SiteHolder siteHolder;

	@Autowired
	private GlobalProperties globalProperties;

	@Autowired
	private DeployService deployServiceImpl;

	@Autowired
	private ObjectMapper objectMapper;

	@Autowired
	private SiteUrlComponent siteUrlComponent;

	@Autowired
	private TemplateService templateServiceImpl;

	@Autowired
	private VelocityEngine velocityEngine;

	@Autowired
	private HtmlCompressor htmlCompressor;

	@Autowired
	private SiteConfigService siteConfigServiceImpl;

	@Override
	public void makeSRHead(SRHead srHead) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException, NotFound404Exception {
		String theme = requestHolder.getAccessSite().getSiteConfig().getTheme();
		ThemeObject themeObject = themeServiceImpl.getThemeObject(theme);

		if (requestHolder == null || requestHolder.getAccessPage() == null || requestHolder.getAccessPage().getSitePage() == null
				|| StrUtil.isBlank(requestHolder.getAccessPage().getSitePage().getTemplateName())) {
			AccessSite accessSite = requestHolder.getAccessSite();
			AccessPage accessPage = requestHolder.getAccessPage();
			String msg = "未能找到模板数据！accessSite: " + accessSite + " accessPage: " + accessPage;
			logger.error(msg);
			throw new NotFound404Exception(msg);
		}
		String templateName = requestHolder.getAccessPage().getSitePage().getTemplateName();

		if (templateName == null) {
			return;
		}

		// 填充 siteHolder 里面关于 seo、code 部分的数据内容，目地是为了对相同数据只做一次查询
//		makeSiteHolder(requestHolder.getAccessSite(), requestHolder.getAccessPage());

		List<ThemeObjectSource> head = themeObject.getHead();
		if (CollUtil.isEmpty(head)) {
			return;
		}

		StringBuilder themeMeta = new StringBuilder();
		StringBuilder title = new StringBuilder();
		StringBuilder dynamicMeta = new StringBuilder();
		StringBuilder sourceInclude = new StringBuilder();
		StringBuilder sourceComponentsjsSource = new StringBuilder();
		StringBuilder sourceThemeSource = new StringBuilder();
		StringBuilder sourceCustomContent = new StringBuilder();
		StringBuilder sourceSourceTags = new StringBuilder();

		for (ThemeObjectSource themeObjectSource : head) {
			String author = themeObjectSource.getAuthor();
			if (!ArrayUtil.<String>contains(AUTHOR, author)) {
				continue;
			}
			String type = themeObjectSource.getType();
			if (type.equals("<ThemeMeta>")) {
				themeMeta.append(makeThemeMeta());
			} else if (type.equals("<Title>")) {
				title.append(title());
			} else if (type.equals("<DynamicMeta>")) {
				dynamicMeta.append(meta());
			} else if (type.equals("<ComponentsjsSource>")) {
				sourceComponentsjsSource.append(makeComponentsjsSource());
			} else if (type.equals("<ThemeSource>")) {
				sourceThemeSource.append(makeThemeSource());
			} else if (type.equals("<CustomContent>")) {
				sourceCustomContent.append("\n" + themeObjectSource.getContent());
			} else if (type.equals("<SourceTags>")) {
				sourceSourceTags.append(makeSourceTags(themeObjectSource.getSource()));
			} else if (StrUtil.startWith(type, "<Include:")) {
				sourceInclude.append(makeInclude(type));
			}
		}

		// favicon.ico 放入动态的
		StringBuilder favicon = favicon();

		StringBuilder dynamicSource = new StringBuilder("\n<!-- dynamicSource -->");

		// 插件部分 plugins
		StringBuilder plugins = plugins();

		StringBuilder endHead = endHead();

		srHead.setTitle(title).setTmeta(themeMeta).setMeta(dynamicMeta).setFavicon(favicon).setSourceInclude(sourceInclude)
				.setSourceComponentsjsSource(sourceComponentsjsSource).setSourceThemeSource(sourceThemeSource).setSourceCustomContent(sourceCustomContent)
				.setSourceComponentsjsSource(sourceComponentsjsSource).setPlugins(plugins).setDynamicSource(dynamicSource).setEndHead(endHead);

	}

	@Override
	public void makeSitemapHtmlSRHead(SRHead srHead)
			throws JsonParseException, JsonMappingException, JsonProcessingException, IOException, NotFound404Exception {

		String theme = requestHolder.getAccessSite().getSiteConfig().getTheme();
		ThemeObject themeObject = themeServiceImpl.getThemeObject(theme);

		if (requestHolder == null || requestHolder.getAccessPage() == null || requestHolder.getAccessPage().getSitePage() == null
				|| StrUtil.isBlank(requestHolder.getAccessPage().getSitePage().getTemplateName())) {
			AccessSite accessSite = requestHolder.getAccessSite();
			AccessPage accessPage = requestHolder.getAccessPage();
			String msg = "未能找到模板数据！accessSite: " + accessSite + " accessPage: " + accessPage;
			logger.error(msg);
			throw new NotFound404Exception(msg);
		}
		String templateName = requestHolder.getAccessPage().getSitePage().getTemplateName();

		if (templateName == null) {
			return;
		}

		// 填充 siteHolder 里面关于 seo、code 部分的数据内容，目地是为了对相同数据只做一次查询
//		makeSiteHolder(requestHolder.getAccessSite(), requestHolder.getAccessPage());

		List<ThemeObjectSource> head = themeObject.getHead();
		if (CollUtil.isEmpty(head)) {
			return;
		}

		StringBuilder themeMeta = new StringBuilder();
		StringBuilder sourceInclude = new StringBuilder();
		StringBuilder sourceComponentsjsSource = new StringBuilder();
		StringBuilder sourceThemeSource = new StringBuilder();
		StringBuilder sourceCustomContent = new StringBuilder();
		StringBuilder sourceSourceTags = new StringBuilder();

		for (ThemeObjectSource themeObjectSource : head) {
			String author = themeObjectSource.getAuthor();
			if (!ArrayUtil.<String>contains(AUTHOR, author)) {
				continue;
			}
			String type = themeObjectSource.getType();
			if (type.equals("<ThemeMeta>")) {
				themeMeta.append(makeThemeMeta());
			} else if (type.equals("<ComponentsjsSource>")) {
				sourceComponentsjsSource.append(makeComponentsjsSource());
			} else if (type.equals("<ThemeSource>")) {
				sourceThemeSource.append(makeThemeSource());
			} else if (type.equals("<CustomContent>")) {
				sourceCustomContent.append("\n" + themeObjectSource.getContent());
			} else if (type.equals("<SourceTags>")) {
				sourceSourceTags.append(makeSourceTags(themeObjectSource.getSource()));
			} else if (StrUtil.startWith(type, "<Include:")) {
				sourceInclude.append(makeInclude(type));
			}
		}

		// favicon.ico 放入动态的
		StringBuilder favicon = favicon();

		StringBuilder dynamicSource = new StringBuilder("\n<!-- dynamicSource -->");

		// plugins
		StringBuilder plugins = plugins();

		srHead.setTmeta(themeMeta).setFavicon(favicon).setSourceInclude(sourceInclude).setSourceComponentsjsSource(sourceComponentsjsSource)
				.setSourceThemeSource(sourceThemeSource).setSourceCustomContent(sourceCustomContent).setSourceComponentsjsSource(sourceComponentsjsSource)
				.setDynamicSource(dynamicSource).setPlugins(plugins);
	}

	@Override
	public StringBuilder plugins() {
		StringBuilder plugins = new StringBuilder();
		plugins.append(
				"\n<script type=\"text/javascript\" src=\"" + siteUrlComponent.getSourcePath("/assets/static/site/public/js/extend.js") + "\"></script>");
		plugins.append("\n<script type=\"text/javascript\" src=\"" + siteUrlComponent.getSourcePath("/assets/static/site/public/js/jquery.global.js")
				+ "\"></script>");
		plugins.append(
				"\n<script type=\"text/javascript\" src=\"" + siteUrlComponent.getSourcePath("/assets/static/site/public/js/jquery.init.js") + "\"></script>");
		plugins.append("\n<script type=\"text/javascript\" src=\"" + siteUrlComponent.getSourcePath("/assets/static/site/public/plugins/layer/layer.js")
				+ "\"></script>");

		return plugins;
	}

	@Override
	public StringBuilder title() {
		StringBuilder title = new StringBuilder();
		try {
			String htmlTitle = seoCodeServiceImpl.title();
			title.append("\n<title>" + HtmlUtils.htmlEscape(htmlTitle) + "</title>");
			title.append("\n<meta name=\"apple-mobile-web-app-title\" content=\"" + HtmlUtils.htmlEscape(htmlTitle) + "\">");
			title.append("\n<meta name=\"apple-mobile-web-app-capable\" content=\"yes\"/>");
		} catch (IOException e) {
			e.printStackTrace();
		}
		return title;
	}

	@Override
	public StringBuilder title(long hostId, long siteId, long systemId, long itemId)
			throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
		SSeoItem sSeoItem = seoServiceImpl.getItemSeoByHostSiteId(hostId, siteId, systemId, itemId);
		StringBuilder title = new StringBuilder();
		String htmlTitle = sSeoItem.getTitle();
		title.append("\n<title>" + HtmlUtils.htmlEscape(htmlTitle) + "</title>");
		title.append("\n<meta name=\"apple-mobile-web-app-title\" content=\"" + HtmlUtils.htmlEscape(htmlTitle) + "\">");
		title.append("\n<meta name=\"apple-mobile-web-app-capable\" content=\"yes\"/>");
		return title;
	}

	@Override
	public StringBuilder meta() throws JsonParseException, JsonMappingException, IOException {
		StringBuilder meta = new StringBuilder();
		String keywords = seoCodeServiceImpl.keywords();
		String description = seoCodeServiceImpl.description();
		String author = seoCodeServiceImpl.author();
		String revisitAfter = seoCodeServiceImpl.revisitAfter();
		List<SSeoSiteSnsConfig> snsConfig = seoCodeServiceImpl.snsConfig();

		// md5 对 biso+[域名] 进行加密
		String biso = SecureUtil.md5("biso" + requestHolder.getRequest().getServerName());

		meta.append("\n<meta name=\"keywords\" content=\"" + HtmlUtils.htmlEscape(keywords) + "\" />");
		meta.append("\n<meta name=\"description\" content=\"" + HtmlUtils.htmlEscape(description) + "\" />");
		meta.append("\n<meta name=\"author\" content=\"" + HtmlUtils.htmlEscape(author) + "\" />");
		meta.append("\n<meta name=\"revisit-after\" content=\"" + HtmlUtils.htmlEscape(revisitAfter) + "\" />");

		if (CollUtil.isNotEmpty(snsConfig)) {
			for (SSeoSiteSnsConfig sSeoSiteSnsConfig : snsConfig) {
				String property = sSeoSiteSnsConfig.getProperty();
				String content = sSeoSiteSnsConfig.getContent();
				meta.append("\n<meta property=\"" + HtmlUtils.htmlEscape(property) + "\" content=\"" + HtmlUtils.htmlEscape(content) + "\" />");
			}
		}

		meta.append("\n<meta name=\"renderer\" content=\"webkit\" />");
//		meta.append("\n<!-- 不让百度转码 -->");
		meta.append("\n<meta http-equiv=\"Cache-Control\" content=\"no-siteapp\" />");
//		meta.append("\n<!-- uc强制竖屏 -->");
		meta.append("\n<meta name=\"screen-orientation\" content=\"portrait\" />");
//		meta.append("\n<!-- QQ强制竖屏 -->");
		meta.append("\n<meta name=\"x5-orientation\" content=\"portrait\" />");
//		meta.append("\n<!-- UC强制全屏 -->");
		meta.append("\n<meta name=\"full-screen\" content=\"yes\" />");
//		meta.append("\n<!-- QQ强制全屏 -->");
		meta.append("\n<meta name=\"x5-fullscreen\" content=\"true\" />");
//		meta.append("\n<!-- UC应用模式 -->");
		meta.append("\n<meta name=\"browsermode\" content=\"application\" />");
//		meta.append("\n<!-- QQ应用模式 -->");
		meta.append("\n<meta name=\"x5-page-mode\" content=\"app\" />");
		meta.append("\n<meta name=\"ibiso\" content=\"" + biso + "\" />");
		String afterMeta = seoCodeServiceImpl.afterMeta();
		meta.append(afterMeta);

		HDomain hDomain = requestHolder.getAccessHost().getHDomain();
		if (hDomain != null && hDomain.getDomainType().shortValue() == (short) 0) {
			Host host = requestHolder.getAccessHost().getHost();
			meta.append("\n<meta name=\"site-token\" content=\"" + host.getRandomCode() + "-" + SecureUtil.sha1(host.getRandomCode()) + "\" />");
		}

		// 模板编号，颜色编号
		String color = "(-1)";
		String theme = "(-1)";
		String templateName = "(-1)";

		if (requestHolder != null && requestHolder.getAccessSite() != null && requestHolder.getAccessSite().getSiteConfig() != null) {
			SConfig siteConfig = requestHolder.getAccessSite().getSiteConfig();
			color = siteConfig.getColor();
			theme = siteConfig.getTheme();

//			HDomain accessHostHDomain = requestHolder.getAccessHost().getHDomain();
//			CTemplateItemData cTemplateItemData = templateServiceImpl.getCTemplateItemDataByUrl(accessHostHDomain);
//			if (cTemplateItemData != null) {
//				templateName = cTemplateItemData.getTemplateName();
//			}else {
//				cTemplateItemData = templateServiceImpl.getCTemplateItemData(requestHolder.getAccessSite().getSiteConfig().getTemplateId());
//				if (cTemplateItemData != null) {
//					templateName = cTemplateItemData.getTemplateName();
//				}
//			}
			CTemplateItemData cTemplateItemData = null;
			Long siteConfigTemplateId = requestHolder.getAccessSite().getSiteConfig().getTemplateId();
			if (siteConfigTemplateId == null || siteConfigTemplateId.longValue() < 1) {
				cTemplateItemData = templateServiceImpl.getCTemplateItemDataByUrl(requestHolder.getAccessHost().getHDomain());
				if (cTemplateItemData != null) {
					templateName = cTemplateItemData.getTemplateName();
				}
			} else {
				cTemplateItemData = templateServiceImpl.getCTemplateItemData(siteConfigTemplateId);
				if (cTemplateItemData != null) {
					templateName = cTemplateItemData.getTemplateName();
					CTemplateItemData cTemplateItemData1 = templateServiceImpl.getCTemplateItemDataByUrl(requestHolder.getAccessHost().getHDomain());
					if (cTemplateItemData1 != null) {
						String templateName2 = cTemplateItemData1.getTemplateName();
						if (StrUtil.isNotBlank(templateName2) && !templateName.equals(templateName2)) {
							long templateId = cTemplateItemData1.getTemplateId();
							String version = cTemplateItemData1.getVersion();
							if (templateId != siteConfigTemplateId.longValue()) {
								// 修改 SiteConfig 的 templateId
								siteConfigServiceImpl.updateTemplateIdVersion(requestHolder.getHostId(), requestHolder.getSiteId(), templateId, version);
							}
							templateName = templateName2;
						}
					}
				} else {
					cTemplateItemData = templateServiceImpl.getCTemplateItemDataByUrl(requestHolder.getAccessHost().getHDomain());
					if (cTemplateItemData != null) {
						templateName = cTemplateItemData.getTemplateName();
					}
				}
			}
		}
		meta.append("\n<meta name=\"Template-Theme-Color\" content=\"" + templateName + "-" + theme + "-" + color + "\" />");

		String basePath = globalProperties.getSite().getBasePath();
		String userPathByCode = SitePathUtil.getUserPathByCode(basePath, requestHolder.getHost().getRandomCode());
		String hostPath = StrUtil.replace(userPathByCode, basePath, "");
		meta.append("\n<meta name=\"Host-Path\" content=\"" + hostPath + "\" />");
		AccessHost accessHost = requestHolder.getAccessHost();
		if (accessHost.getHost().getEndAt() != null) {
			meta.append("\n<meta name=\"End-At\" content=\"" + (new SimpleDateFormat("yyyy-MM-dd")).format(accessHost.getHost().getEndAt()) + "\" />");
		}

		return meta;
	}

	@Override
	public StringBuilder meta(long hostId, long siteId, long systemId, long itemId) throws JsonParseException, JsonMappingException, IOException {
		SSeoItem sSeoItem = seoServiceImpl.getItemSeoByHostSiteId(hostId, siteId, systemId, itemId);

		StringBuilder meta = new StringBuilder();
		String keywords = sSeoItem.getKeywords();
		String description = sSeoItem.getDescription();
		String author = seoCodeServiceImpl.author();
		String revisitAfter = seoCodeServiceImpl.revisitAfter();
		List<SSeoSiteSnsConfig> snsConfig = seoCodeServiceImpl.snsConfig();

		meta.append("\n<meta name=\"keywords\" content=\"" + keywords + "\" />");
		meta.append("\n<meta name=\"description\" content=\"" + description + "\" />");
		meta.append("\n<meta name=\"author\" content=\"" + author + "\" />");
		meta.append("\n<meta name=\"revisit-after\" content=\"" + revisitAfter + "\" />");

		if (CollUtil.isNotEmpty(snsConfig)) {
			for (SSeoSiteSnsConfig sSeoSiteSnsConfig : snsConfig) {
				String property = sSeoSiteSnsConfig.getProperty();
				String content = sSeoSiteSnsConfig.getContent();
				meta.append("\n<meta property=\"" + property + "\" content=\"" + content + "\" />");
			}
		}

		String afterMeta = seoCodeServiceImpl.afterMeta();
		meta.append(afterMeta);

		return meta;
	}

	@Override
	public StringBuilder favicon() {
		// 通过 basePath 以及 code 获取 用户的目录
		String userPathByCode = SitePathUtil.getUserPathByCode(globalProperties.getSite().getBasePath(), requestHolder.getHost().getRandomCode());
		String filefullpath = userPathByCode + "/favicon.ico";
		File faviconFile = new File(filefullpath.toString());
		// 删除原来的图片
		if (!faviconFile.isFile()) {
			return new StringBuilder();
		}
		StringBuilder favicon = new StringBuilder();
		favicon.append("\n<!-- favicon.ico -->");
		String faviconPath = siteUrlComponent.getfaviconPath("/favicon.ico");
		favicon.append("\n<link rel=\"icon\" href=\"" + faviconPath + "\" type=\"image/ico\" />");
		favicon.append("\n<link rel=\"shortcut icon\" href=\"" + faviconPath + "\" type=\"image/ico\" media=\"screen\" />");
		return favicon;
	}

	@Override
	public StringBuilder endHead() {
		StringBuilder endHead = new StringBuilder();
		String beforeEndHead = seoCodeServiceImpl.beforeEndHead();

		endHead.append(beforeEndHead);
		return endHead;
	}

	@Override
	public void remakeHRHeadTitleMate(long hostId, long siteId, long systemId, long itemId)
			throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
		StringBuilder title = title(hostId, siteId, systemId, itemId);
		StringBuilder meta = meta(hostId, siteId, systemId, itemId);

		SRHtml srHtml = siteHolder.getSRHtml();
		SRHead head = srHtml.getHead();
		head.setTitle(title).setMeta(meta);
	}

	@Override
	public void remakeform() {
		SRHtml srHtml = siteHolder.getSRHtml();
		SRHead head = srHtml.getHead();
		StringBuilder form = head.getForm();
		if (StringUtils.isEmpty(form.toString())) {
			form = new StringBuilder("\n<!-- form javascript -->");
			String src = siteUrlComponent.getSourcePath("/assets/static/site/public/js/jquery.biso.form.js");
			form.append("\n<script type=\"text/javascript\" src=\"" + src + "\"></script>\n");
			head.setForm(form);
		}
	}

//	public void makeSiteHolder(AccessSite accessSite, AccessPage accessPage)
//			throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
//		SitePage sitePage = accessPage.getSitePage();
//		SSystem system = accessPage.getSystem();
//		long hostId = accessSite.getSite().getHostId().longValue();
//		long siteId = accessSite.getSite().getId().longValue();
//		long pageId = sitePage.getSPage().getId().longValue();
//
//		makeSiteHolderSiteSeo(hostId, siteId);
//
//		makeSiteHolderPageSeo(hostId, siteId, pageId);
//
//		SCategories sCategories = sitePage.getSCategories();
//		if (system != null && sCategories != null) {
//			makeSiteHolderCategorySeo(hostId, siteId, system.getId().longValue(), sCategories.getId().longValue());
//		}
//
//		makeSiteHolderHostCode(hostId);
//
//		makeSiteHolderSiteCode(hostId, siteId);
//
//		makeSiteHolderPageCode(hostId, siteId, pageId);
//
//	}

//	public void makeSiteHolderSiteSeo(long hostId, long siteId) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
//		SeoService seoServiceImpl = SpringContextUtils.getBean("seoServiceImpl", SeoService.class);
//		SSeoSite sSeoSite = seoServiceImpl.getSiteSeoByHostSiteId(hostId, siteId);
//		siteHolder.setSeoSite(sSeoSite);
//	}
//
//	public void makeSiteHolderPageSeo(long hostId, long siteId, long pageId)
//			throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
//		SeoService seoServiceImpl = SpringContextUtils.getBean("seoServiceImpl", SeoService.class);
//		SSeoPage sSeoPage = seoServiceImpl.getPageSeoByHostSiteId(hostId, siteId, pageId);
//		siteHolder.setSeoPage(sSeoPage);
//	}
//
//	public void makeSiteHolderCategorySeo(long hostId, long siteId, long systemId, long categoryId)
//			throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
//		SeoService seoServiceImpl = SpringContextUtils.getBean("seoServiceImpl", SeoService.class);
//		SSeoCategory sSeoCategory = seoServiceImpl.getCategorySeoByHostSiteId(hostId, siteId, systemId, categoryId);
//		siteHolder.setSeoCategory(sSeoCategory);
//	}
//
//	public void makeSiteHolderHostCode(long hostId) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
//		CodeService codeServiceImpl = SpringContextUtils.getBean("codeServiceImpl", CodeService.class);
//		SCodeSite sCodeSite = codeServiceImpl.getCodeSiteByHostSiteId(hostId, 0L);
//		siteHolder.setCodeHost(sCodeSite);
//	}
//
//	public void makeSiteHolderSiteCode(long hostId, long siteId) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
//		CodeService codeServiceImpl = SpringContextUtils.getBean("codeServiceImpl", CodeService.class);
//		SCodeSite sCodeSite = codeServiceImpl.getCodeSiteByHostSiteId(hostId, siteId);
//		siteHolder.setCodeSite(sCodeSite);
//	}
//
//	public void makeSiteHolderPageCode(long hostId, long siteId, long pageId)
//			throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
//		CodeService codeServiceImpl = SpringContextUtils.getBean("codeServiceImpl", CodeService.class);
//		SCodePage sCodePage = codeServiceImpl.getCodePageByHostSiteId(hostId, siteId, pageId);
//		siteHolder.setCodePage(sCodePage);
//	}

	@Override
	public StringBuilder makeThemeMeta() throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
		String theme = requestHolder.getAccessSite().getSiteConfig().getTheme();
		if (StrUtil.isBlank(theme)) {
			return new StringBuilder("\n<!-- 未能获取到 theme -->");
		}
		return makeThemeMeta(theme);
	}

	@Override
	public StringBuilder makeThemeMeta(String theme) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
		StringBuilder make = new StringBuilder("\n<!-- ThemeMeta -->");
		// 根据模板中的 head <meta 标签写入 head 中
		Pattern pattern = Pattern.compile("<meta.*?>", Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
		Matcher matcher = pattern.matcher(themeServiceImpl.getThemeHead(theme, requestHolder.getAccessPage().getSitePage().getTemplateName()));
		while (matcher.find()) {
			String meta = matcher.group(0);
			make.append("\n" + meta);
		}
		return make;
	}

	@Override
	public StringBuilder makeComponentsjsSource() throws IOException {
		StringBuilder make = new StringBuilder("\n<!-- ComponentsjsSource -->");
		String componentjsVersion = deployServiceImpl.componentJsVersion();
		String componentsCss = siteUrlComponent.getSourcePath("/assets/deploy/components/dist-udin.css?v=" + componentjsVersion);
		String componentsJS = siteUrlComponent.getSourcePath("/assets/deploy/components/dist-udin.js?v=" + componentjsVersion);
		make.append("\n<link type=\"text/css\" rel=\"stylesheet\" href=\"" + componentsCss + "\" />");
		make.append("\n<script type=\"text/javascript\" src=\"" + componentsJS + "\"></script>");
		return make;
	}

	@Override
	public StringBuilder makeThemeSource() throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
		String theme = null;
		String color = null;
		if (requestHolder != null && requestHolder.getAccessSite() != null && requestHolder.getAccessSite().getSiteConfig() != null) {
			theme = requestHolder.getAccessSite().getSiteConfig().getTheme();
			color = requestHolder.getAccessSite().getSiteConfig().getColor();
		}
		if (StrUtil.isBlank(theme)) {
			return new StringBuilder("\n<!-- 未能获取到 theme -->");
		}
		return makeThemeSource(theme, color);
	}

	@Override
	public StringBuilder makeThemeSource(String theme, String color) {
		StringBuilder make = new StringBuilder("\n<!-- ThemeCssSource -->");
		String colorLink = "/assets/static/site/np_template/" + theme + "/css/color_" + color + ".css";
		if (!NumberUtil.isNumber(color)) {
			long siteId = requestHolder.getSiteId();
			String enSiteId = String.valueOf(siteId);
			try {
				enSiteId = CryptoJava.en(String.valueOf(siteId));
			} catch (Exception e) {
			}
			SConfig siteConfig = requestHolder.getAccessSite().getSiteConfig();
			String customThemeColorConfig = siteConfig.getCustomThemeColorConfig();
			colorLink += "?si=" + enSiteId + "&ctcc=" + SecureUtil.md5(customThemeColorConfig).toLowerCase();
		}
		String[] link = { "/assets/static/site/np_template/" + theme + "/css/theme.css", colorLink };
		for (String str : link) {
			make.append("\n<link type=\"text/css\" rel=\"stylesheet\" href=\"" + siteUrlComponent.getSourcePath(str) + "\">");
		}
		make.append(makeThemeJsSource(theme, color));
		return make;
	}

	@Override
	public StringBuilder makeThemeJsSource() {
		String theme = null;
		String color = null;
		if (requestHolder != null && requestHolder.getAccessSite() != null && requestHolder.getAccessSite().getSiteConfig() != null) {
			theme = requestHolder.getAccessSite().getSiteConfig().getTheme();
			color = requestHolder.getAccessSite().getSiteConfig().getColor();
		}
		if (StrUtil.isBlank(theme)) {
			return new StringBuilder("\n<!-- 未能获取到 theme -->");
		}
		return makeThemeJsSource(theme, color);
	}

	@Override
	public StringBuilder makeThemeJsSource(String theme, String color) {
		StringBuilder make = new StringBuilder("\n<!-- ThemeJsSource -->");
		String[] script = { "/assets/static/site/np_template/" + theme + "/js/theme.js" };
		for (String str : script) {
			make.append("\n<script type=\"text/javascript\" src=\"" + siteUrlComponent.getSourcePath(str) + "\"></script>");
		}
		return make;
	}

	@Override
	public StringBuilder makeSourceTags(List<ThemeObjectHtmlTag> source) throws IOException {
		StringBuilder stringBuilder = new StringBuilder("<!-- SourceTags -->");
		if (CollUtil.isEmpty(source)) {
			return stringBuilder;
		}
		stringBuilder.append(makeThemeObjectHtmlTag(source));
		return stringBuilder;
	}

	@Override
	public StringBuilder makeInclude(String type) throws JsonParseException, JsonMappingException, IOException {
		StringBuilder stringBuilder = new StringBuilder("\n<!-- Include Source -->");
		Pattern pattern = Pattern.compile("<Include:(.*)>");
		Matcher matcher = pattern.matcher(type);
		String sourceSrc = null;
		if (matcher.find()) {
			sourceSrc = StrUtil.trim(matcher.group(1));
		}
		if (StrUtil.isBlank(sourceSrc)) {
			stringBuilder.append("\n<!-- SourceSrc Empty! type: " + type + " -->");
			return stringBuilder;
		}
		String source = ThemeUtil.getInclude(sourceSrc, globalProperties.getSite().getAssetsPath());
		if (StrUtil.isBlank(source)) {
			stringBuilder.append("\n<!-- Source Empty! type: " + type + " -->");
			return stringBuilder;
		}

		List<ThemeObjectHtmlTag> themeObjectHtmlTagList = objectMapper.readValue(source, new TypeReference<List<ThemeObjectHtmlTag>>() {
		});
		if (CollUtil.isEmpty(themeObjectHtmlTagList)) {
			stringBuilder.append("\n<!-- List<ThemeObjectHtmlTag> Empty! type: " + type + " -->");
			return stringBuilder;
		}
		stringBuilder.append(makeThemeObjectHtmlTag(themeObjectHtmlTagList));
		return stringBuilder;
	}

	private StringBuilder makeThemeObjectHtmlTag(List<ThemeObjectHtmlTag> list) {
		StringBuilder stringBuilder = new StringBuilder();
		if (CollUtil.isEmpty(list)) {
			return stringBuilder;
		}

		for (ThemeObjectHtmlTag themeObjectHtmlTag : list) {
			String tag = themeObjectHtmlTag.getTag();
			if (tag.equals("<NULL>")) {
				stringBuilder.append("\n" + themeObjectHtmlTag.getContent());
			} else {
				if (StrUtil.isBlank(tag)) {
					continue;
				}
				StringBuilder tagHtml = new StringBuilder("\n" + "<" + tag);
				List<ThemeObjectHtmlTagAttrs> attrs = themeObjectHtmlTag.getAttrs();
				if (CollUtil.isNotEmpty(attrs)) {
					for (ThemeObjectHtmlTagAttrs attr : attrs) {
						String name = attr.getName();
						String value = attr.getValue();
						if (tag.equals("link") && name.equals("href") && themeObjectHtmlTag.getPrefix() != null && themeObjectHtmlTag.getPrefix() == true) {
							value = siteUrlComponent.getSourcePath(value);
						} else if (tag.equals("script") && name.equals("src") && themeObjectHtmlTag.getPrefix() != null
								&& themeObjectHtmlTag.getPrefix() == true) {
							value = siteUrlComponent.getSourcePath(value);
						}
						tagHtml.append(" " + name + "=\"" + value + "\"");
					}
				}
				boolean vod = themeObjectHtmlTag.getVod() == null ? true : themeObjectHtmlTag.getVod();
				if (tag.equals("link")) {
					vod = true;
				} else if (tag.equals("script")) {
					vod = false;
				}

				if (vod) {
					tagHtml.append(" />");
				} else {
					String content = themeObjectHtmlTag.getContent();
					tagHtml.append(">" + (StrUtil.isBlank(content) ? "" : "\n" + content + "\n") + "</" + tag + ">");
				}
				stringBuilder.append(tagHtml);
			}
		}
		return stringBuilder;
	}

	@Override
	public void dynamicHeadSource(SRHead srHead) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException, NotFound404Exception {
		StringBuilder sourceComponentsjsSource = srHead.getSourceComponentsjsSource();
		// 判断是否是IE浏览器，如果不是则加入 three 脚本
		HttpServletRequest request = requestHolder.getRequest();
		boolean msBrowser = UserAgentUtil.isMSBrowser(request.getHeader("User-Agent"));
		if (!msBrowser) {
			String sourcePath = siteUrlComponent.getSourcePath("/assets/static/site/np_template/js/three.min.js");
			sourceComponentsjsSource.insert(0, "\n<script type=\"text/javascript\" src=\"" + sourcePath + "\"></script>");
		}
		AccessPage accessPage = requestHolder.getAccessPage();
		SitePage sitePage = accessPage.getSitePage();
		SSystem sSystem = sitePage.getSSystem();
		if (sSystem != null) {
			sourceComponentsjsSource.append("\n<script type=\"text/javascript\" src=\"/assets/static/site/np_template/js/menuH.js\"></script>");
			sourceComponentsjsSource.append("\n<script type=\"text/javascript\" src=\"/assets/static/site/np_template/js/menuV.js\"></script>");
		}
	}

	@Override
	public void dynamicAppendEndHead(SRHead srHead)
			throws JsonParseException, JsonMappingException, JsonProcessingException, IOException, NotFound404Exception {
		StringBuilder dynamicAppendEndHead = new StringBuilder();

		AccessHost accessHost = requestHolder.getAccessHost();
		HConfig hostConfig = accessHost.getHostConfig();

		StringBuilder siteGray = siteGray(hostConfig);
		if (StrUtil.isNotBlank(siteGray)) {
			dynamicAppendEndHead.append(siteGray);
		}

		srHead.getEndHead().append(dynamicAppendEndHead);
	}

	protected StringBuilder siteGray(HConfig hostConfig) {
		if (hostConfig == null) {
			return null;
		}
		Short siteGray = hostConfig.getSiteGray();
		if (siteGray != null && siteGray.shortValue() == (short) 1) {
			Template template = velocityEngine.getTemplate("templates/css/site_gray.vm");
			StringWriter sw = new StringWriter();
			template.merge(null, sw);
			return new StringBuilder("\n" + htmlCompressor.compress(sw.toString()));
		}
		return null;
	}
}
